這是篇觀察EF Core執行時行為的測試筆記,若有謬誤繁請指正
public class Song: BaseField
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { set; get; }
public string Name { set; get; }
public string Descrption { set; get; }
public virtual ICollection<SongRecord> SongRecords { set; get; }
public Song()
{
this.SongRecords = new List<SongRecord>();
}
}
public class SongRecord : BaseField
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { set; get; }
[ForeignKey("Song")]
public int SongId { set; get; }
public DateTime Time { set; get; }
public string Listener { set; get; }
public string SongUrl { set; get; }
public virtual Song Song { set; get; }
}
1.1、若直接取回實體,由於消極式載入機制,其關聯的SongRecords欄位為空
var lazy_q = Context.Songs;
var lazy_m = lazy_q.ToList();
觀察變數lazy_m:
1.2、變數lazy_m已是toList後的實體, SongRecords依舊為空
var lazy_child_t = lazy_m.SelectMany(x=>x.SongRecords).ToList();
觀察變數lazy_child_t:
1.3、在這裡使用到了 SongRecords欄位,則取回實體後, SongRecords欄位有值
var lazy_child_q = lazy_q.SelectMany(y => y.SongRecords);
var lazy_child_m = lazy_child_q.ToList();
觀察變數lazy_child_m:
1.4、執行到此,回頭看上面的變數 lazy_m ,由於預設行為會進行tracking, 變數lazy_m偵測到變數 lazy_child_m 取回了 SongRecords 的資料,則其 SongRecords欄位會被填入值
觀察變數lazy_m:
1.5、若不想進行tracking,則呼叫AsNoTracking()方法,取回的實體便是單純的實體,不會發生(第1.4節)的行為
var lazy_m = lazy_q.AsNoTracking().ToList();
指定 SongRecords欄位後取回實體,將一併取回包含 SongRecords欄位的所有資料
var eager_q = Context.Songs.Include(x => x.SongRecords);
var eager_m = eager_q.ToList();
觀察變數eager_m:
在明確需要實體時呼叫load(),以明確載入實體
var song = Context.Songs.FirstOrDefault();
觀察變數song:
執行後,欄位 SongRecords的實體資料被填入,注意必須在tracking的狀態才能使用load()
Context.Entry(song).Collection(x => x.SongRecords).Query().Load();
觀察變數song: